package io.sundial.core;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 原子对象
 *
 * @author Payne 646742615@qq.com
 * 2018/12/20 20:54
 */
public class Atomic {
    private final ReadWriteLock rwLock = new ReentrantReadWriteLock();

    public <R, E extends Exception> R doReadingCommand(AtomicRTCommand<R, E> command) throws E {
        rwLock.readLock().lock();
        try {
            return command.run();
        } finally {
            rwLock.readLock().unlock();
        }
    }

    public <R> R doReadingCommand(AtomicRNCommand<R> command) {
        rwLock.readLock().lock();
        try {
            return command.run();
        } finally {
            rwLock.readLock().unlock();
        }
    }

    public <E extends Exception> void doReadingCommand(AtomicVTCommand<E> command) throws E {
        rwLock.readLock().lock();
        try {
            command.run();
        } finally {
            rwLock.readLock().unlock();
        }
    }

    public void doReadingCommand(AtomicVNCommand command) {
        rwLock.readLock().lock();
        try {
            command.run();
        } finally {
            rwLock.readLock().unlock();
        }
    }

    public <R, E extends Exception> R doWritingCommand(AtomicRTCommand<R, E> command) throws E {
        rwLock.writeLock().lock();
        try {
            return command.run();
        } finally {
            rwLock.writeLock().unlock();
        }
    }

    public <R> R doWritingCommand(AtomicRNCommand<R> command) {
        rwLock.writeLock().lock();
        try {
            return command.run();
        } finally {
            rwLock.writeLock().unlock();
        }
    }

    public <E extends Exception> void doWritingCommand(AtomicVTCommand<E> command) throws E {
        rwLock.writeLock().lock();
        try {
            command.run();
        } finally {
            rwLock.writeLock().unlock();
        }
    }

    public void doWritingCommand(AtomicVNCommand command) {
        rwLock.writeLock().lock();
        try {
            command.run();
        } finally {
            rwLock.writeLock().unlock();
        }
    }

}
